home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AOL File Library: 2,801 to 2,900
/
aol-file-protocol-4400-2801-to-2900.zip
/
AOLDLs
/
C++ Files Library
/
MRDiim, 3D World Shell
/
MRDiim.sit
/
MRDiim
/
MRConstruction.cp
< prev
next >
Wrap
Text File
|
1994-12-19
|
11KB
|
436 lines
#include<QDOffScreen.h>
#include"Utils_General.h"
#include"MRRachet.h"
#include"MREyeBall.h"
#include"MRConstruction.h"
#include"MRDiim.h"
#include <math.h>
//wall's pattern for fill
extern PixPatHandle WallPenPattern[2][3];
MRConstruction::MRConstruction(short Number,Boolean toMark) : MRRachet(Number,toMark)
{
myBuildType=0;
myStructure=nil;
myActors=nil;
oDistance = 0;
// clears this everytime a new one is added (static)
maxDist=0;
nextDist=0;
myWallType=0;
}
// statics
static float MRConstruction::maxDist;
static float MRConstruction::nextDist;
MRConstruction::~MRConstruction(void)
{
if(GetNum()!=0)
{
switch(myBuildType)
{
case 1:
{
delete((ChartPost *)myStructure);
delete((ChartPost *)myActors);
break;
}
case 2:
{
delete((ChartWall *)myStructure);
delete((ChartWall *)myActors);
break;
}
}
}
}
void *MRConstruction::NewRachet(short Number,Boolean toMark)
{
return(new MRConstruction(Number,toMark));
}
void MRConstruction::ZapRachet(Ptr toBeZapped)
{
delete (MRConstruction *) toBeZapped;
}
void MRConstruction::AddConstruction(ChartPost theCP, char wallType)
{ // post
if(HasNext())
((MRConstruction *) NextRachet)->AddConstruction(theCP,wallType);
else
{
// create the next link
CreateNew(GetMarked());
// create a ChartPost for the data set
((MRConstruction *) NextRachet)->myStructure=new ChartPost;
// I think that this copies the contents of theCP into the rachet's data structure
* ((ChartPost *) (((MRConstruction *) NextRachet)->myStructure)) = theCP;
// create a ChartPost Actors
((MRConstruction *) NextRachet)->myActors=new ChartPost;
// copy data into the actors (not used, just filler)
* ((ChartPost *) (((MRConstruction *) NextRachet)->myActors)) = ZeroZeroPost;
// mark the dataset as a post [1]
((MRConstruction *) NextRachet)->myBuildType = 1;
// set the wallType
((MRConstruction *) NextRachet)->myWallType = wallType;
}
}
void MRConstruction::AddConstruction(ChartWall theCW, char wallType)
{ // wall
if(HasNext())
((MRConstruction *) NextRachet)->AddConstruction(theCW,wallType);
else
{
// create the next link
CreateNew(GetMarked());
// create a ChartWall for the data set
((MRConstruction *) NextRachet)->myStructure=new ChartWall;
// I think that this copies the contents of theCP into the rachet's data structure
* ((ChartWall *) (((MRConstruction *) NextRachet)->myStructure)) = theCW;
// create a ChartWall Actor
((MRConstruction *) NextRachet)->myActors=new ChartWall;
// copy data into the actors (not used, just filler)
* ((ChartWall *) (((MRConstruction *) NextRachet)->myActors)) = ReturnChartWall(ZeroZeroPost,ZeroZeroPost);
// mark the dataset as a wall [2]
((MRConstruction *) NextRachet)->myBuildType = 2;
// set the wallType
((MRConstruction *) NextRachet)->myWallType = wallType;
}
}
void MRConstruction::FindActors(ChartPost myself,float facing,Boolean halfCircle)
{
ChartPost actor1={0,0};
ChartPost actor2={0,0};
if(GetNum()==0)
{
maxDist=MaxViewDistance;
nextDist=0;
}
else
{
switch(myBuildType)
{
case 1:
{
actor1 = FindActor(DiffChartPost(myself,* ((ChartPost *) myStructure) ),facing,halfCircle);
* (ChartPost *) myActors = actor1;
oDistance = sqrt(actor1.myX*actor1.myX+actor1.myY*actor1.myY);
break;
}
case 2:
{
actor1 = FindActor(DiffChartPost(myself,(* ((ChartWall *) myStructure)).CP1),facing,halfCircle);
actor2 = FindActor(DiffChartPost(myself,(* ((ChartWall *) myStructure)).CP2),facing,halfCircle);
if(((actor1.myY>0)&&(actor2.myY<0))||((actor1.myY<0)&&(actor2.myY>0)))
{ // crosses y=0, fix it so it's seen
// get the slope
float slopeMainLine = (actor2.myY-actor1.myY)/( (actor2.myX-actor1.myX)==0 ? .017 : (actor2.myX-actor1.myX) ) ;
// we don't want exactly zero
if(slopeMainLine==0)
slopeMainLine=.017;
// get b of the line
float bMainLine = actor1.myY - (slopeMainLine*actor1.myX);
// prepare the X intercept in case of a close wall
float theCrossX = -bMainLine/slopeMainLine;
if ( (theCrossX<1) &&(theCrossX>=0) )
theCrossX = 1;
if ( (theCrossX>-1) &&(theCrossX<0) )
theCrossX = -1;
// replace the point behind line of sight
if(actor1.myY>0)
actor2=ReturnChartPost(theCrossX,0);
else
actor1=ReturnChartPost(theCrossX,0);
}
* (ChartWall *) myActors = ReturnChartWall(actor1,actor2);
oDistance = sqrt(pow((actor1.myX+actor2.myX)/2,2)+pow((actor1.myY+actor2.myY)/2,2));
break;
}
}
}
SetMarked((oDistance<MaxViewDistance) && (actor1.myY>=0));
if(HasNext())
((MRConstruction *) NextRachet)->FindActors(myself,facing,halfCircle);
}
void MRConstruction::PrepScanStart(void)
{
maxDist = MaxViewDistance;
nextDist = 0;
}
void MRConstruction::PrepScan(void)
{
nextDist = 0;
}
void MRConstruction::ScanConstruction(void)
{
if(GetMarked())
{
if((oDistance<maxDist) && (oDistance>nextDist))
nextDist=oDistance;
if(HasNext())
((MRConstruction *) NextRachet)->ScanConstruction();
if(nextDist==oDistance)
{
DoConstruction();
SetMarked(false);
}
}
else
if(HasNext())
((MRConstruction *) NextRachet)->ScanConstruction();
}
Boolean MRConstruction::ProposedMove(ChartPost myMove)
{ // is the proposed move going to keep me from bumping into walls ?
Boolean returnedPM=true; // assume the best
ChartPost actor1={0,0};
ChartPost actor2={0,0};
ChartPost segment={0,0};
float bMainLine;
ChartPost inter;
if(HasNext())
returnedPM = ((MRConstruction *) NextRachet)->ProposedMove(myMove);
if(returnedPM==false)
return(returnedPM);
switch(myBuildType)
{
case 1:
{
actor1=DiffChartPost(myMove,* (ChartPost *) myStructure);
if(sqrt(pow(actor1.myX,2)+pow(actor1.myY,2))>HumanStep)
return(true);
else
return(false);
break;
}
case 2:
{ // get tan of line, invert, use to get equation of pt through line. calc intersection & distance. if in question, solve for between pts
float slopeMainLine;
float slopeSecondLine;
actor1=DiffChartPost(myMove,(* (ChartWall *) myStructure).CP1);
actor2=DiffChartPost(myMove,(* (ChartWall *) myStructure).CP2);
segment=DiffChartPost(actor1,actor2);
if(segment.myX==0)
segment.myX=.017;
slopeMainLine=segment.myY/segment.myX;
if(slopeMainLine==0)
slopeMainLine=.017;
slopeSecondLine=(-1/slopeMainLine);
bMainLine = actor2.myY-(slopeMainLine*actor2.myX);
inter.myX=bMainLine/(slopeSecondLine-slopeMainLine);
inter.myY=slopeSecondLine*inter.myX;
// get an ordered list of the points
ChartWall orderedList=LowHigh(actor1,actor2);
// fix the line to within the box
if(orderedList.CP1.myX>inter.myX)
inter.myX=orderedList.CP1.myX;
if(orderedList.CP1.myY>inter.myY)
inter.myY=orderedList.CP1.myY;
if(orderedList.CP2.myX<inter.myX)
inter.myX=orderedList.CP2.myX;
if(orderedList.CP2.myY<inter.myY)
inter.myY=orderedList.CP2.myY;
// if the line comes nowhere near us, return OK/true
if(sqrt(pow(inter.myX,2)+pow(inter.myY,2))>HumanStep)
return(true);
else
return(false);
break;
}
default: // default for zero!
return(true);
}
}
void MRConstruction::DoConstruction(void)
{
if(GetNum()!=0)
{
switch(myBuildType)
{
case 1:
{
DrawPost(* (ChartPost *) myActors);
break;
}
case 2:
{
DrawWall((* (ChartWall *) myActors).CP1,(* (ChartWall *) myActors).CP2,myWallType);
break;
}
}
}
}
void DrawPost(ChartPost CP)
{
Point refPoint={0,0};
refPoint = FindFooter(CP);
MoveTo(refPoint.h+HorizonLine,refPoint.v+MeridianLine);
LineTo(refPoint.h+HorizonLine,MeridianLine-refPoint.v);
}
void DrawWall(ChartPost CP1,ChartPost CP2,char wallType)
{
Point refPoint1={0,0};
Point refPoint2={0,0};
PolyHandle triPoly;
refPoint1=FindFooter(CP1);
refPoint2=FindFooter(CP2);
triPoly = OpenPoly();
MoveTo(refPoint1.h+HorizonLine,refPoint1.v+MeridianLine);
LineTo(refPoint1.h+HorizonLine,MeridianLine-refPoint1.v);
LineTo(refPoint2.h+HorizonLine,MeridianLine-refPoint2.v);
LineTo(refPoint2.h+HorizonLine,refPoint2.v+MeridianLine);
LineTo(refPoint1.h+HorizonLine,refPoint1.v+MeridianLine);
ClosePoly();
switch((short) Min(CP1.myY,CP2.myY))
{
case 0:
case 1:
FillCPoly (triPoly, WallPenPattern[wallType][0]);break;
case 2:
case 3:
FillCPoly (triPoly, WallPenPattern[wallType][1]);break;
case 4:
case 5:
FillCPoly (triPoly, WallPenPattern[wallType][2]);break;
default :
FillPoly(triPoly,black);break;
}
FramePoly(triPoly);
// if(QDError != noErr)
// DoError("\pCan't draw Polygon. No memory?");
KillPoly(triPoly);
}
Point FindFooter(ChartPost CP)
{ // use to place a footer (x,y) onto the screen with "realism"
Point refPoint={0,0};
if(CP.myY<0)
refPoint.v=MeridianLine-atan2(-(CP.myY),UnitHeight)*MerdSpan;
else
refPoint.v=MeridianLine-atan2(CP.myY,UnitHeight)*MerdSpan;
refPoint.h= refPoint.v*CP.myX*ViewRatio;
return(refPoint);
}
ChartPost FindActor(ChartPost target,float rads, Boolean halfCircle)
{ // target must be in relative terms. info passed back in actorY,actorY
// get the slope of the line that runs perpendicular to the way we are looking
float slopeMainLine=tan(rads);
if(slopeMainLine==0)
slopeMainLine=.017; // we don't want exactly zero
float slopeSecondLine=(-1/slopeMainLine);
// get the B of the second line (y=slope*x+b, where b is 0 in first equation)
float bSecondLine = target.myY-(slopeSecondLine*target.myX);
// calculate the intersection of the line and a perpendicular line through the point
ChartPost inter={bSecondLine/(slopeMainLine-slopeSecondLine),slopeMainLine*inter.myX};
// find the actor!
ChartPost actor={sqrt(inter.myX*inter.myX+inter.myY*inter.myY),sqrt(pow(target.myX-inter.myX,2)+pow(inter.myY-target.myY,2))};
// fix the sign if angled to the left
if(inter.myX<0)
actor.myX= -actor.myX;
// fix the direction of angled backwards
if(!halfCircle)
actor.myX = -actor.myX;
// if it's behind us,flip the sign
if(!(halfCircle==false && (target.myX*slopeMainLine)<target.myY) && !(halfCircle==true && (target.myX*slopeMainLine)>target.myY))
actor.myY = -actor.myY;
return(actor);
}
void NormalizeAngle(float &facing, Boolean &halfCircle)
{
if(facing<-MyHalfPi)
{
facing+=MyPi;
halfCircle= !halfCircle;
}
if(facing>MyHalfPi)
{
facing-=MyPi;
halfCircle = !halfCircle;
}
}
ChartPost ReturnChartPost(float myX,float myY)
{
ChartPost CP={myX,myY};
return (CP);
}
ChartWall ReturnChartWall(ChartPost CP1,ChartPost CP2)
{
ChartWall CW={CP1.myX,CP1.myY,CP2.myX,CP2.myY};
return(CW);
}
ChartWall LowHigh(ChartPost lowCP,ChartPost highCP)
{ // reorders coordinates of box to low->high and adds margin of error
ChartWall CW={Min(lowCP.myX,highCP.myX)-.1,Min(lowCP.myY,highCP.myY)-.1,Max(lowCP.myX,highCP.myX)+.1,Max(lowCP.myY,highCP.myY)+.1};
return(CW);
// float slopeMainLine = (CP2.myY-CP1.myY)/( (CP2.myX-CP1.myX)==0 ? .017 : (CP2.myX-CP1.myX) ) ;
// if(slopeMainLine==0)
// slopeMainLine=.017;
// float tanMainLine = atan(slopeMainLine);
// CP1.myX-=cos(tanMainLine);
// CP1.myY-=sin(tanMainLine);
// CP2.myX+=cos(tanMainLine);
// CP2.myY+=sin(tanMainLine);
// lowCP=CP1;
// highCP=CP2;
}